// use crate::project::Project;
use crate::image::{ImageBuilder, Rect};
use crate::prequire::{
  adb::{screenshot::ScreenshotCmd, shell::ShellCmd},
  BinaryCommand,
};
// use chrono::prelude::*;
// use clap::Subcommand;
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use std::fs::create_dir_all;
use std::io;
use std::path::Path;
use std::sync::mpsc::channel;
use std::thread;
// use std::time::Duration;
// use std::fmt;




// #[derive(Debug, Subcommand)]
// pub enum ProjectScreenCommands {
//   Capture {
//     #[arg(short, long, default_value_t = 1, default_missing_value = "1")]
//     num: usize,

//     #[arg(short, long)]
//     train: bool,

//     #[arg(short, long, default_value_t = false)]
//     preprocess: bool,
//   },
//   CaptureOld {
//     #[arg(short, long, default_value_t = 1, default_missing_value = "1")]
//     num: usize,

//     #[arg(short, long)]
//     train: bool,

//     #[arg(short, long, default_value_t = false)]
//     preprocess: bool,
//   },
// }

// pub fn serve_commands(proj: &Project, command: &ProjectScreenCommands) {
//   match command {
//     ProjectScreenCommands::Capture {
//       num,
//       train,
//       preprocess,
//     } => {
//       start_app(&proj.proj_conf.app.name).expect("failed start app");
//       thread::sleep(Duration::from_millis(5000));
//       let fragment = iif!(
//         *train,
//         format!(
//           "{}/{:?}",
//           &proj.proj_conf.app.capture_dir.display(),
//           CaptureCategory::Train
//         ),
//         format!(
//           "{}/{:?}",
//           &proj.proj_conf.app.capture_dir.display(),
//           CaptureCategory::Screenshot
//         )
//       );
//       let capture_dir = format!(
//         "{}/{}/{}",
//         proj.location.as_os_str().to_str().unwrap(),
//         fragment,
//         Utc::now().timestamp_millis(),
//       );

//       ShellCmd::new(
//         &["input swipe 600 2155 600 1405"],
//         Some(Box::new(|_| String::from(""))),
//       )
//       .exec().expect("shell input swipe failed");

//       let ctr = Catcher::new(&capture_dir, *preprocess);
//       if let Ok(success) = ctr.capture_mtt_list(*num) {
//         if success {
//           println!(
//             "截图成功保存在{}!",
//             proj.proj_conf.app.capture_dir.display()
//           );
//         }
//       }
//     }
//     ProjectScreenCommands::CaptureOld {
//       num,
//       train,
//       preprocess,
//     } => {
//       start_app(&proj.proj_conf.app.name).expect("failed start app");
//       thread::sleep(Duration::from_millis(5000));
//       let fragment = iif!(
//         *train,
//         format!(
//           "{}/{:?}",
//           &proj.proj_conf.app.capture_dir.display(),
//           CaptureCategory::Train
//         ),
//         format!(
//           "{}/{:?}",
//           &proj.proj_conf.app.capture_dir.display(),
//           CaptureCategory::Screenshot
//         )
//       );
//       let capture_dir = format!(
//         "{}/{}/{}",
//         proj.location.as_os_str().to_str().unwrap(),
//         fragment,
//         Utc::now().timestamp_millis(),
//       );
//       let ctr = Catcher::new(&capture_dir, *preprocess);
//       if let Ok(success) = ctr.capture_mtt_list_old(*num) {
//         if success {
//           println!(
//             "截图成功保存在{}!",
//             proj.proj_conf.app.capture_dir.display()
//           );
//         }
//       }

//       // v1 速度太慢
//       // if let Ok(success) =
//       //   ScreenshotCmd::new(&self.package.name, *num, &self.package.capture_dir).exec()
//       // {
//       //   if success {
//       //     println!("截图成功保存在{}!", self.package.capture_dir.display());
//       //   }
//       // }
//     }
//   }
// }

pub struct Catcher<P>
where
  P: AsRef<Path>,
{
  out_dir: P,
  preprocess: bool,
}

impl<P> Catcher<P>
where
  P: AsRef<Path>,
{
  pub fn new(out_dir: P, preprocess: bool) -> Self {
    println!("cacher outdir{}", out_dir.as_ref().display());
    create_dir_all(out_dir.as_ref()).expect("create_dir_all fail!");
    return Catcher {
      out_dir,
      preprocess,
    };
  }
  fn new_multi_process(&self) -> (MultiProgress, ProgressStyle) {
    let m = MultiProgress::new();
    let sty =
      ProgressStyle::with_template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")
        .unwrap()
        .progress_chars("##-");

    (m, sty)
  }
  pub fn capture_mtt_list(&self, num: usize) -> io::Result<bool> {
    let steps = num as u64;
    let (m, sty) = self.new_multi_process();
    let (tx, rx) = channel();
    // pb负责从设备截图到本地
    let pb = m.add(ProgressBar::new(steps));
    pb.set_style(sty.clone());
    // pb2负责将一页图分割
    let pb2 = m.insert_after(&pb, ProgressBar::new(steps));
    pb2.set_style(sty.clone());
    // pb3负责将分割后的图像进行预处理(剪切,灰度)
    let pb3 = m.insert_after(&pb2, ProgressBar::new(steps));
    pb3.set_style(sty);
    m.println("starting!").unwrap();

    let capture_dir = self.out_dir.as_ref().to_path_buf();
    let m_clone = m.clone();
    let h1 = thread::spawn(move || {
      for i in 0..num {
        pb.set_message(format!("screen capturing item #{}", i + 1));

        let out = format!("{}/{}.png", capture_dir.display(), i);
        // use adb take screenshot
        if let Err(err) = ScreenshotCmd::new(out).exec() {
          eprintln!("截图失败!\n{}", err);
          m_clone.println("截图失败!").unwrap();
          pb.abandon_with_message("中止");
          return;
        }
        tx.send(i).unwrap();
        pb.inc(1);
        if let Err(err) = ShellCmd::new(
          &["input swipe 600 2155 600 1105"],
          Some(Box::new(|_| String::from(""))),
        )
        .exec()
        {
          eprintln!("滚动失败!\n{}", err);
          continue;
        }
      }
      m_clone.println("截图完成!").unwrap();
      pb.finish_with_message("成功");
    });
    let _ = h1.join();

    let capture_dir = self.out_dir.as_ref().to_path_buf();
    let m_clone = m.clone();
    let h2 = thread::spawn(move || {
      for i in rx {
        // println!("v=>{:?}", v);
        pb2.set_message(format!("separate item #{}", i + 1));

        // use adb binarization image
        let src = format!("{}/{}.png", capture_dir.display(), i);

        println!("src png =>{}", src);

        // if let Ok(()) = ImageSegmentator::new(src)
        // // .set_boudary_color(Rgba([245, 245, 245, 255]))
        // // .set_sampling_size(36)
        // // .set_right_padding(64)
        // // .set_left_crop(355)
        // .set_boudary_color(*boudary_color)
        // .set_sampling_size(*sampling_size)
        // .set_left_padding(*left_padding)
        // .set_right_padding(*right_padding)
        // .set_left_crop(*left_crop)
        // .set_right_crop(*right_crop)
        // .split()
        // {
        //   println!("done!");
        // } else {
        //   eprintln!("can't RecognitionEx image!");
        // };
        // if let Err(err) = ImageBuilder::new(src)
        //   .set_crop(Rect::new(355, 355, 700, 1820))
        //   .set_binarization(true)
        //   .save()
        // {
        //   eprintln!("预处理失败!\n{}", err);
        //   m_clone.println("预处理失败!").unwrap();
        //   pb2.abandon_with_message("中止");
        //   return;
        // }

        pb2.inc(1);
        // thread::sleep(Duration::from_millis(700));
      }
      m_clone.println("预处理完成!").unwrap();
      pb2.finish_with_message("成功");
    });
    let _ = h2.join();

    m.clear().unwrap();
    Ok(true)
  }
  pub fn capture_mtt_list_old(&self, num: usize) -> io::Result<bool> {
    // move to page start
    ShellCmd::new(
      &["input swipe 600 2155 600 1405"],
      Some(Box::new(|_| String::from(""))),
    )
    .exec()?;

    let (m, sty) = self.new_multi_process();
    let (tx, rx) = channel();
    let pb = m.add(ProgressBar::new(num as u64));
    pb.set_style(sty.clone());
    let pb2 = m.insert_after(&pb, ProgressBar::new(num as u64));
    pb2.set_style(sty);
    m.println("starting!").unwrap();
    let capture_dir = self.out_dir.as_ref().to_path_buf();
    let m_clone = m.clone();
    let h1 = thread::spawn(move || {
      for i in 0..num {
        pb.set_message(format!("screen capturing item #{}", i + 1));

        let out = format!("{}/{}.png", capture_dir.display(), i);
        // use adb take screenshot
        if let Err(err) = ScreenshotCmd::new(out).exec() {
          eprintln!("截图失败!\n{}", err);
          m_clone.println("截图失败!").unwrap();
          pb.abandon_with_message("中止");
          return;
        }
        tx.send(i).unwrap();
        pb.inc(1);
        if let Err(err) = ShellCmd::new(
          &["input swipe 600 2155 600 1105"],
          Some(Box::new(|_| String::from(""))),
        )
        .exec()
        {
          eprintln!("滚动失败!\n{}", err);

          continue;
        }
      }
      m_clone.println("截图完成!").unwrap();
      pb.finish_with_message("成功");
    });
    let _ = h1.join();

    if self.preprocess {
      let capture_dir = self.out_dir.as_ref().to_path_buf();
      let m_clone = m.clone();
      let h2 = thread::spawn(move || {
        for i in rx {
          // println!("v=>{:?}", v);
          pb2.set_message(format!("preprocessing item #{}", i + 1));

          // use adb binarization image
          let src = format!("{}/{}.png", capture_dir.display(), i);

          if let Err(err) = ImageBuilder::new(src)
            .set_crop(Rect::new(355, 355, 700, 1820))
            .set_binarization(true)
            .save()
          {
            eprintln!("预处理失败!\n{}", err);
            m_clone.println("预处理失败!").unwrap();
            pb2.abandon_with_message("中止");
            return;
          }
          pb2.inc(1);
          // thread::sleep(Duration::from_millis(700));
        }
        m_clone.println("预处理完成!").unwrap();
        pb2.finish_with_message("成功");
      });
      let _ = h2.join();
    }

    m.clear().unwrap();
    Ok(true)
  }
}
